﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using GASS.CUDA.Types;
using GASS.CUDA;
using System.Diagnostics;

namespace Sandbox
{
    public static class Util
    {
        /// <summary>
        /// Devuelve un float entre 0.0f y 1.0f
        /// </summary>
        public static float NextFloat(this Random random)
        {
            return (float)random.NextDouble();
        }

        /// <summary>
        /// Devuelve un Vector3 cuyas componentes estan entre 0.0f y 1.0f
        /// </summary>
        public static Vector3 NextVector3(this Random random)
        {
            return new Vector3(random.NextFloat(), random.NextFloat(), random.NextFloat());
        }

        /// <summary>
        /// Devuelve un Vector3 entre min y max.
        /// </summary>
        public static Vector3 NextVector3(this Random random, Vector3 min, Vector3 max)
        {
            return new Vector3(
                DenormalizeTo(random.NextFloat(), min.X, max.X),
                DenormalizeTo(random.NextFloat(), min.Y, max.Y),
                DenormalizeTo(random.NextFloat(), min.Z, max.Z)
            );
        }

        /// <summary>
        /// Value es una variable aleatoria entre 0 y 1, este metodo
        /// la denormalize para el intervalo (min, max)
        /// </summary>
        public static float DenormalizeTo(float value, float min, float max)
        {
            return value * (max - min) + min;
        }

        /// <summary>
        /// Devuelve un color opaco aleatorio.
        /// </summary>
        public static Color NextColor(this Random random)
        {
            return new Color(random.NextVector3());
        }

        public static Float3 AddF3(Float3 f1, Float3 f2)
        {
            return new Float3() { x = f1.x + f2.x, y = f1.y + f2.y, z = f1.z + f2.z};
        }

        public static Float3 SubF3(Float3 f1, Float3 f2)
        {
            return new Float3() { x = f1.x - f2.x, y = f1.y - f2.y, z = f1.z - f2.z };
        }

        public static Float3 ToF3(Vector3 v)
        {
            return new Float3() { x = v.X, y = v.Y, z = v.Z };
        }

        public static Vector3 ToV3(Float3 v)
        {
            return new Vector3() { X = v.x, Y = v.y, Z = v.z };
        }

        public static void CheckCUDA()
        {
            cudaError error = CUDARuntime.cudaGetLastError();
            if (error != cudaError.cudaSuccess)
            {
                throw new Exception("CUDA has thrown an error.");
            }
        }
    }
}
